package com.wut.easypoi.utils;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
import cn.hutool.core.util.StrUtil;
import com.wut.core.config.exception.GlobalException;
import java.io.File;
import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import javax.servlet.http.HttpServletResponse;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.multipart.MultipartFile;

@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class ExcelUtil {

    /**
     * Excel导出(无标题)
     *
     * @param list      数据
     * @param sheetName sheet名称
     * @param pojoClass pojo类型
     * @param fileName  文件名称
     * @param response  response
     */
    public static void exportExcelNoTitle(List<?> list, Class<?> pojoClass, String fileName, String sheetName, ExcelType excelType, HttpServletResponse response) {
        ExportParams exportParams = new ExportParams(null, sheetName, excelType);
        defaultExport(list, pojoClass, fileName, response, exportParams, ExcelTypeEnum.getExcelType(excelType));
    }

    /**
     * Excel导出
     *
     * @param list      数据
     * @param title     标题
     * @param sheetName sheet名称
     * @param pojoClass pojo类型
     * @param fileName  文件名称
     * @param response  response
     */
    public static void exportExcel(List<?> list, Class<?> pojoClass, String fileName, String sheetName, String title, ExcelType excelType, HttpServletResponse response) {
        defaultExport(list, pojoClass, fileName, response, new ExportParams(title, sheetName, excelType), ExcelTypeEnum.getExcelType(excelType));
    }

    /**
     * Excel导出
     *
     * @param list         数据
     * @param pojoClass    pojo类型
     * @param fileName     文件名称
     * @param response     response
     * @param exportParams 导出参数
     */
    public static void exportExcel(List<?> list, Class<?> pojoClass, String fileName, ExportParams exportParams, ExcelTypeEnum excelType, HttpServletResponse response) {
        defaultExport(list, pojoClass, fileName, response, exportParams, excelType);
    }

    /**
     * Excel导出
     *
     * @param list     数据
     * @param fileName 文件名称
     * @param response response
     */
    public static void exportExcel(List<Map<String, Object>> list, String fileName, ExcelTypeEnum excelType, HttpServletResponse response) {
        defaultExport(list, fileName, response, excelType);
    }

    /**
     * 默认的 Excel导出
     *
     * @param list         数据
     * @param pojoClass    pojo类型
     * @param fileName     文件名称
     * @param response     response
     * @param exportParams 导出参数
     */
    private static void defaultExport(List<?> list, Class<?> pojoClass, String fileName, HttpServletResponse response, ExportParams exportParams, ExcelTypeEnum excelType) {
        Workbook workbook = ExcelExportUtil.exportExcel(exportParams, pojoClass, list);
        downLoadExcel(fileName, response, workbook, excelType);
    }

    /**
     * 默认的 Excel导出
     *
     * @param list     数据
     * @param fileName 文件名称
     * @param response response
     */
    private static void defaultExport(List<Map<String, Object>> list, String fileName, HttpServletResponse response, ExcelTypeEnum excelType) {
        Workbook workbook = ExcelExportUtil.exportExcel(list, ExcelType.HSSF);
        downLoadExcel(fileName, response, workbook, excelType);
    }

    /**
     * 下载
     *
     * @param fileName 文件名称
     * @param response response
     * @param workbook excel数据
     */
    private static void downLoadExcel(String fileName, HttpServletResponse response, Workbook workbook, ExcelTypeEnum excelType) {
        try {
            response.setCharacterEncoding(StandardCharsets.UTF_8.name());
            //response.setHeader(HttpHeaders.CONTENT_TYPE, "application/vnd.ms-excel");
            response.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_OCTET_STREAM_VALUE);
            response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + URLEncoder.encode(fileName + "." + excelType.getValue(), StandardCharsets.UTF_8.name()));
            workbook.write(response.getOutputStream());
        } catch (Exception e) {
            throw new GlobalException(e.getMessage());
        }
    }

    /**
     * Excel导入
     *
     * @param filePath   excel文件路径
     * @param titleRows  标题行
     * @param headerRows 表头行
     * @param pojoClass  pojo类型
     */
    public static <T> List<T> importExcel(String filePath, Integer titleRows, Integer headerRows, Class<T> pojoClass) {
        if (StringUtils.isBlank(filePath)) {
            return Collections.emptyList();
        }
        ImportParams params = new ImportParams();
        params.setTitleRows(titleRows);
        params.setHeadRows(headerRows);
        params.setNeedSave(true);
        params.setSaveUrl("/excel/");
        try {
            return ExcelImportUtil.importExcel(new File(filePath), pojoClass, params);
        } catch (NoSuchElementException e) {
            throw new GlobalException("模板不能为空");
        } catch (Exception e) {
            throw new GlobalException(e.getMessage());
        }
    }

    /**
     * Excel导入
     *
     * @param file      excel文件
     * @param pojoClass pojo类型
     */
    public static <T> List<T> importExcel(MultipartFile file, Class<T> pojoClass) {
        return importExcel(file, 1, 1, pojoClass);
    }

    /**
     * Excel导入
     *
     * @param file       excel文件
     * @param titleRows  标题行
     * @param headerRows 表头行
     * @param pojoClass  pojo类型
     */
    public static <T> List<T> importExcel(MultipartFile file, Integer titleRows, Integer headerRows, Class<T> pojoClass) {
        return importExcel(file, titleRows, headerRows, false, pojoClass);
    }

    /**
     * Excel导入
     *
     * @param file       上传的文件
     * @param titleRows  标题行
     * @param headerRows 表头行
     * @param needVerify 是否检验excel内容
     * @param pojoClass  pojo类型
     */
    public static <T> List<T> importExcel(MultipartFile file, Integer titleRows, Integer headerRows, boolean needVerify, Class<T> pojoClass) {
        if (file == null) {
            return Collections.emptyList();
        }
        try {
            return importExcel(file.getInputStream(), titleRows, headerRows, needVerify, pojoClass);
        } catch (Exception e) {
            throw new GlobalException(e.getMessage());
        }
    }

    /**
     * Excel导入
     *
     * @param inputStream 文件输入流
     * @param titleRows   标题行
     * @param headerRows  表头行
     * @param needVerify  是否检验excel内容
     * @param pojoClass   pojo类型
     */
    public static <T> List<T> importExcel(InputStream inputStream, Integer titleRows, Integer headerRows, boolean needVerify, Class<T> pojoClass) {
        if (inputStream == null) {
            return Collections.emptyList();
        }
        ImportParams params = new ImportParams();
        params.setTitleRows(titleRows);
        params.setHeadRows(headerRows);
        params.setSaveUrl("/excel/");
        params.setNeedSave(true);
        params.setNeedVerify(needVerify);
        try {
            return ExcelImportUtil.importExcel(inputStream, pojoClass, params);
        } catch (NoSuchElementException e) {
            throw new GlobalException("excel文件不能为空");
        } catch (Exception e) {
            throw new GlobalException(e.getMessage());
        }
    }

    /**
     * Excel 类型枚举
     */
    enum ExcelTypeEnum {
        XLS("xls"),
        XLSX("xlsx");

        private String value;

        ExcelTypeEnum(String value) {
            this.value = value;
        }

        public String getValue() {
            return value;
        }

        void setValue(String value) {
            this.value = value;
        }

        public static ExcelTypeEnum getExcelType(ExcelType excelType) {
            if (StrUtil.equalsIgnoreCase("XSSF", excelType.name())) {
                return ExcelTypeEnum.XLSX;
            }
            return ExcelTypeEnum.XLS;
        }
    }
}